home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld 1998 September
/
Macworld (1998-09).dmg
/
Shareware World
/
Info
/
For Developers
/
MacZoop 1.8.3
/
Required Classes
/
Z Sources
/
ZObjectArray.cpp
< prev
next >
Wrap
Text File
|
1998-07-10
|
9KB
|
331 lines
/*************************************************************************************************
*
*
* MacZoop - "the framework for the rest of us"
*
*
*
* ZObjectArray.cpp -- a container for objects (template class)
*
*
*
*
*
* © 1996, Graham Cox
*
*
*
*
*************************************************************************************************/
#include "ZObjectArray.h"
#include "ZErrors.h"
#include "ZDefines.h"
#include "ZStream.h"
/*---------------------------------*** CONSTRUCTOR ***---------------------------------*/
template <class T> ZObjectArray<T>::ZObjectArray()
: ZArray( sizeof(T*) )
{
classID = CLASS_ZObjectArray;
// we manipulate our handle via <o> rather than <a> so we can take advantage
// of direct register copies, etc for maximum performance, which is what this
// class is all about (it avoids BlockMove).
o = (T***) a;
}
/*----------------------------------*** GETOBJECT ***----------------------------------*/
/*
return the object at <index>
-----------------------------------------------------------------------------------------*/
template <class T> T* ZObjectArray<T>::GetObject( const long index )
{
// gets the item at position <index> in the array. Index is one-based.
if ((index < 1) || (index > numElements))
FailOSErr( kIndexOutOfRangeErr );
return ((*o)[index - 1]);
}
/*--------------------------------*** DELETEOBJECT ***---------------------------------*/
/*
delete the object at <index> from the array. Does not dispose of the object itself
-----------------------------------------------------------------------------------------*/
template <class T> void ZObjectArray<T>::DeleteObject(T* item)
{
long index;
index = FindIndex( item );
if (index > 0)
DeleteItem ( index );
}
/*---------------------------------*** DISPOSEALL ***----------------------------------*/
/*
disposes of all of the objects in the array
-----------------------------------------------------------------------------------------*/
template <class T> void ZObjectArray<T>::DisposeAll()
{
// calls ForgetObject for every object in the array, then forces the array empty. Since
// it is possible for ForgetObject to modify this array, we iterate in reverse order.
long i = numElements;
T* p;
while(i--)
{
p = (*o)[i];
if (p)
ForgetObject(p);
}
SetHandleSize( a, 0 );
numElements = 0;
}
/*----------------------------------*** DOFOREACH ***----------------------------------*/
/*
calls the grovelling function for every object in the array
-----------------------------------------------------------------------------------------*/
template <class T> void ZObjectArray<T>::DoForEach( IteratorProcPtr aProc, const long ref )
{
// calls the grovelling function for every object in the array.
if (aProc && (numElements > 0))
{
long i = numElements;
while(i)
(*aProc)((*o)[--i] , ref);
}
}
/*-----------------------------------*** CONTAINS ***----------------------------------*/
/*
returns TRUE if the object can be found in the array
-----------------------------------------------------------------------------------------*/
template <class T> Boolean ZObjectArray<T>::Contains(T* item)
{
return (FindIndex( item ) > 0);
}
/*--------------------------------*** SETARRAYITEM ***---------------------------------*/
/*
overrides the inherited method to store objects in the list avoiding BlockMove().
-----------------------------------------------------------------------------------------*/
template <class T> void ZObjectArray<T>::SetArrayItem( void* item, const long index )
{
if ((index < 1) || (index > numElements))
FailOSErr( kIndexOutOfRangeErr );
(*o)[index - 1] = (T*) item;
}
/*--------------------------------*** GETARRAYITEM ***---------------------------------*/
/*
overrides the inherited method to obtain objects in the list avoiding BlockMove().
-----------------------------------------------------------------------------------------*/
template <class T> void ZObjectArray<T>::GetArrayItem( void* item, const long index )
{
if ((index < 1) || (index > numElements))
FailOSErr( kIndexOutOfRangeErr );
*(T**)item = ((*o)[index - 1]);
}
/*-----------------------------*** CONCATENATEARRAY ***--------------------------------*/
/*
joins another similar array to the end of this one. The source array must be of the same
type and is uaffected by the copy. Since the arrays contain object refs, note that both
arrays will have the same objects in them after this, so take care.
-----------------------------------------------------------------------------------------*/
template <class T> void ZObjectArray<T>::ConcatenateArray( ZObjectArray<T>* anArray )
{
ZArray::ConcatenateArray((ZArray*) anArray );
}
/*----------------------------------*** FINDINDEX ***----------------------------------*/
/*
return the index of the object, or zero if not found.
-----------------------------------------------------------------------------------------*/
template <class T> long ZObjectArray<T>::FindIndex(T* item)
{
if ( numElements < 1 )
return 0;
long i = 0;
Boolean found = FALSE;
do
{
if ((*o)[i] == item)
{
found = TRUE;
break;
}
}
while( ++i < numElements );
return ( found? i + 1 : 0 );
}
/*-------------------------------------*** SWAP ***------------------------------------*/
/*
swaps the items at indices a and b- can be used within sorts, etc
-----------------------------------------------------------------------------------------*/
template <class T> void ZObjectArray<T>::Swap( const long itema, const long itemb )
{
register T* temp;
if ((itema < 1) ||
(itema > numElements) ||
(itemb < 1) ||
(itemb > numElements))
FailOSErr( kIndexOutOfRangeErr );
temp = GetObject( itema );
(*o)[itema - 1] = (*o)[itemb - 1];
(*o)[itemb - 1] = temp;
}
/*-----------------------------------*** MOVEITEM ***----------------------------------*/
/*
moves the object at index <curIndex> to the index <newIndex>, displacing other items
as needed. Completely overrides the ZArray method for better efficiency and to eliminate
"pointer to pointer to object" dereferencing difficulties.
-----------------------------------------------------------------------------------------*/
template <class T> void ZObjectArray<T>::MoveItem( const long curIndex, const long newIndex )
{
register T* temp;
if ((curIndex < 1) ||
(curIndex > numElements) ||
(newIndex < 1) ||
(newIndex > numElements))
FailOSErr( kIndexOutOfRangeErr );
// don't do anything if indices the same (not an error)
if ( curIndex != newIndex )
{
temp = GetObject( curIndex );
DeleteItem( curIndex );
InsertItem( temp, newIndex );
SendMessage( msgArrayItemMoved, (void*) newIndex );
}
}
/*---------------------------------*** MOVETOFRONT ***---------------------------------*/
/*
moves the object at index <curIndex> to the front of the list (1)
-----------------------------------------------------------------------------------------*/
template <class T> void ZObjectArray<T>::MoveToFront( const long index )
{
MoveItem( index, 1 );
}
/*----------------------------------*** MOVETOBACK ***---------------------------------*/
/*
moves the object at index <curIndex> to the back of the list (n)
-----------------------------------------------------------------------------------------*/
template <class T> void ZObjectArray<T>::MoveToBack( const long index )
{
MoveItem( index, CountItems());
}
/*-------------------------------*** WRITETOSTREAM ***--------------------------------*/
/*
write entire array object to stream. Since this array holds objects, we save each one
as an object reference, not the same way that ZArray works. Note that <T> must be derived
from ZObject and registered with <gClasses> for this to work, but when it does work the
power this unleashes is astonishing!
----------------------------------------------------------------------------------------*/
template <class T> void ZObjectArray<T>::WriteToStream( ZStream* aStream )
{
ZComrade::WriteToStream( aStream );
register long i;
// count of objects to follow:
aStream->WriteLong( numElements );
// write the object references as needed:
for ( i = 1; i <= numElements; i++ )
aStream->WriteObject( GetObject( i ));
}
/*------------------------------*** READFROMSTREAM ***--------------------------------*/
/*
read entire array back from stream. This refills the array with objects built from the
stream. These objects are equivalent to the ones saved in the stream originally, and
have the same type and function.
----------------------------------------------------------------------------------------*/
template <class T> void ZObjectArray<T>::ReadFromStream( ZStream* aStream )
{
ZComrade::ReadFromStream( aStream );
register T* temp;
register long i, numObjects;
aStream->ReadLong( &numObjects );
// size the storage handle as needed to hold this many objects:
if ( numElements != numObjects )
{
SetHandleSize( a, numObjects * blkSize );
FailMemError();
numElements = numObjects;
}
for ( i = 1; i <= numObjects; i++ )
{
temp = (T*) aStream->ReadObject();
SetArrayItem( temp, i );
}
}